package by.dezhits.liltweets.images;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import by.dezhits.liltweets.ContextHolder;
import by.dezhits.liltweets.task.ImageAsyncTask;

public class ImageLoader {
	

	private static ImageLoader instance;

	public static ImageLoader getInstance() {
		if (instance == null) {
			instance = new ImageLoader();
		}
		return instance;
	}

	private LruCache<String, Bitmap> mStorage;

	private List<Callback> mQueue;

	public enum ConvertOnLoadMode {
		ROUND, NORMAL
	}

	public interface Callback {

		String getUrl();

		ConvertOnLoadMode getLoadMode();

		void success(Bitmap bm);

		void onError(Exception e);
	}

	private ImageLoader() {
		int memClass = ((ActivityManager) ContextHolder.getInstance()
				.getContext().getSystemService(Context.ACTIVITY_SERVICE))
				.getMemoryClass();
		final int cacheSize = 1024 * 1024 * memClass / 4;
		// final int cacheSize = 50*1024;
		mStorage = new LruCache<String, Bitmap>(cacheSize) {
			@Override
			protected int sizeOf(String key, Bitmap value) {
				return value.getRowBytes() * value.getHeight();
			}

			@Override
			protected void entryRemoved(boolean evicted, String key,
					Bitmap oldValue, Bitmap newValue) {
				if (evicted) {
					oldValue.recycle();
					//System.gc();
					oldValue = null;
				}
			}
		};
		mQueue = Collections.synchronizedList(new ArrayList<Callback>());
	}

	public void bind(final BaseAdapter adapter, final ImageView imageView,
			final String url, final ConvertOnLoadMode mode) {
		Bitmap bitmap = null;

		if ((bitmap = mStorage.get(url)) != null) {
			imageView.setImageBitmap(bitmap);
		} else {
			mQueue.add(0, new Callback() {

				@Override
				public void success(Bitmap bm) {
					adapter.notifyDataSetChanged();
				}

				@Override
				public String getUrl() {
					return url;
				}

				@Override
				public ConvertOnLoadMode getLoadMode() {
					return mode;
				}

				@Override
				public void onError(Exception e) {
					Log.d("ImageLoader",e.getMessage());
				}
			});
		}
		proceed();
	}

	public void bind(final ImageView imageView, final String url,
			final ConvertOnLoadMode mode, final boolean checkTag) {
		Bitmap bitmap = null;
		final Object oldTag = imageView.getTag();
		if ((bitmap = mStorage.get(url)) != null) {
			if (checkTag) {
				if (oldTag.equals(imageView.getTag())) {
					imageView.setImageBitmap(bitmap);
				}

			} else {
				imageView.setImageBitmap(bitmap);
			}
		} else {
			mQueue.add(0, new Callback() {

				@Override
				public void success(final Bitmap bm) {
					mStorage.put(url, bm);
					if (checkTag) {
						if (oldTag.equals(imageView.getTag())) {
							imageView.setImageBitmap(bm);
						}

					} else {
						imageView.setImageBitmap(bm);
					}

				}

				@Override
				public ConvertOnLoadMode getLoadMode() {
					return mode;
				}

				@Override
				public String getUrl() {
					return url;
				}

				@Override
				public void onError(Exception e) {

				}

			});
		}
		proceed();
	}

	private void proceed() {
		if (mQueue.isEmpty()) {
			return;
		}
		final Callback callback = mQueue.remove(0);
		new ImageAsyncTask(callback).start(callback.getUrl());
	}
}
